package main

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"project/study-go/config"
	_ "project/study-go/db"
	"project/study-go/logger"
	"project/study-go/util"
	_ "project/study-go/validate"

	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
)

var (
	//全局server对象
	server *http.Server
	//server关闭管道
	exit chan os.Signal
	//graceperiod when server shutdown
	gracePeriod = time.Second * 5
)

func main() {
	var (
		err error
	)
	//flush to disk after server shutdown
	defer logger.Flush()

	//prepare for staring server
	err = ReadyForServer()
	if err != nil {
		logger.RoutineLogger.Error(err.Error())
		return
	}
	logger.RoutineLogger.Info("All Components required by the server were ready！")

	//init gin
	gin.SetMode(config.Vip.GetString("server.ginMode"))
	logger.RoutineLogger.Infof("Gin Default mode: %s.", gin.Mode())

	//root route
	e := gin.New()
	pprof.Register(e)
	RegisterRoutes(e)

	//start server
	go startServer(e)
	exit = make(chan os.Signal, 1)
	signal.Notify(exit, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)

	//监听关闭服务器信号
	select {
	case sig := <-exit:
		logger.RoutineLogger.Warnf("Recieved os.signal %s ", sig.String())
		stopServer()
	}

	//清洁工作
	err = CleanUpServer()
	if err != nil {
		logger.RoutineLogger.Info(err.Error())
	}
	logger.RoutineLogger.Info("CleanUp success after server shutdown.")
}

//server start listen
func startServer(e *gin.Engine) {
	host := config.Vip.GetString("server.host")
	port := config.Vip.GetString("server.port")
	server = &http.Server{
		Addr:    host + ":" + port,
		Handler: e,
	}
	//判断是否
	serverMode := config.Vip.GetString("server.mode")
	if strings.ToUpper(serverMode) == "HTTP" {
		logger.RoutineLogger.Infof("HTTP server start Listen on %s:%s", host, port)
		server.ListenAndServe()
	} else if strings.ToUpper(serverMode) == "HTTPS" {
		certfile := config.Vip.GetString("server.cert")
		keyfile := config.Vip.GetString("server.key")
		//判断证书与公钥文件是否存在
		if util.FileNotExist(certfile) {
			logger.RoutineLogger.Fatal("There are no cert file in your specifc path.")
		} else if util.FileNotExist(keyfile) {
			logger.RoutineLogger.Fatal("There are no key file in your specifc path.")
		}
		logger.RoutineLogger.Infof("HTTPS server start Listen on %s:%s", host, port)
		server.ListenAndServeTLS(certfile, keyfile)
	}
}

//shutdown server
func stopServer() {
	logger.RoutineLogger.Warnf("Server will be close in %f seconds ......", gracePeriod.Seconds())
	ctx, _ := context.WithTimeout(context.Background(), gracePeriod)
	err := server.Shutdown(ctx)
	if err != nil {
		logger.RoutineLogger.Errorf("An error occur \"%s\"", err.Error())
	}
	logger.RoutineLogger.Info("Server closed!")
}
